/**
 * @file i2c_master.h
 * @date 2017-12-20
 *
 * NOTE:
 * This file is generated by DAVE. Any manual modification done to this file will be lost when the code is
 * regenerated.
 */
/**
 * @cond
 ***********************************************************************************************************************
 * I2C_MASTER v4.1.24 Configures USIC channel to transmit & receive data using I2C protocol.
 *
 * Copyright (c) 2015-2017, Infineon Technologies AG
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
 * following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
 * disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 * following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
 * products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes
 * with Infineon Technologies AG (dave@infineon.com).
 ***********************************************************************************************************************
 *
 * Change History
 * --------------
 *
 * 2015-02-16:
 *     - Initial version<br>
 *
 * 2015-06-10:
 *     - AbortTransmit and AbortReceive API return type modified. <br>
 *
 * 2015-08-31:
 *     - DMA support APIs added
 * 2015-10-20:
 *     - Code snippets updated
 * 2016-08-18:
 *     - Documentation of slave address formatting improved.
 * 2017-11-17:
 *     - Added tx_irqn and rx_irqn to I2C_MASTER_CONFIG_t
 * 2017-12-20:
 *     - Added I2C_MASTER_FlushTxFifo(), I2C_MASTER_FlushRxFifo(), I2C_MASTER_DisableOutputs(), I2C_MASTER_EnableOutputs()
 *
 * @endcond
 *
 */

#ifndef I2C_MASTER_H
#define I2C_MASTER_H



/***********************************************************************************************************************
 * HEADER FILES
 **********************************************************************************************************************/
#include <xmc_gpio.h>
#include <xmc_i2c.h>
#include "i2c_master_conf.h"

#if(UC_FAMILY == XMC4)
#if ((I2C_MASTER_DMA_TX_ENABLED == 1) || (I2C_MASTER_DMA_RX_ENABLED == 1))
#include "GLOBAL_DMA/global_dma.h"
#endif
#endif

#include <DAVE_Common.h>


typedef void(*i2c_master_fptr_cbhandler)(void);

/***********************************************************************************************************************
 * MACROS
 **********************************************************************************************************************/
#if (!((XMC_LIB_MAJOR_VERSION == 2U) && \
       (XMC_LIB_MINOR_VERSION >= 0U) && \
       (XMC_LIB_PATCH_VERSION >= 0U)))
#error "I2C_MASTER requires XMC Peripheral Library v2.0.0 or higher"
#endif

/***********************************************************************************************************************
 * ENUMS
 **********************************************************************************************************************/
/**
 * @ingroup I2C_MASTER_enumerations
 * @{
 */
/**
 * Initialization status.
 */
typedef enum I2C_MASTER_STATUS
{
  I2C_MASTER_STATUS_SUCCESS = 0U,           /*!< I2C_MASTER SUCCESS */
  I2C_MASTER_STATUS_FAILURE = 1U,           /*!< I2C_MASTER FAILURE */
  I2C_MASTER_STATUS_BUSY = 2U,              /*!< I2C_MASTER BUSY */
  I2C_MASTER_STATUS_UNSUPPORTED_MODE = 3U   /*!< I2C_MASTER UNSUPPORTED MODE */
} I2C_MASTER_STATUS_t;

/**
 * Direction
 */
typedef enum I2C_MASTER_DIRECTION
{
  I2C_MASTER_DIRECTION_TRANSMIT = 0U,   /*!< Direction indicates transmit */
  I2C_MASTER_DIRECTION_RECEIVE = 1U     /*!< Direction indicates receive */
} I2C_MASTER_DIRECTION_t;

/**
 * @brief Enum used to identify the transfer type used for either transmit or receive function.
 */
typedef enum I2C_MASTER_TRANSFER_MODE
{
  I2C_MASTER_TRANSFER_MODE_INTERRUPT,  /**< Implement data transmit or receive using interrupts */
  I2C_MASTER_TRANSFER_MODE_DMA,        /**< Implement data transmit or receive using DMA */
  I2C_MASTER_TRANSFER_MODE_DIRECT      /**< This configuration exposes signals for external APP connection */
} I2C_MASTER_TRANSFER_MODE_t;
/**
 * @}
 */
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/

/**
 * @ingroup I2C_MASTER_datastructures
 * @{
 */
/**
 * @brief Structure for DMA configuration.
 */
#if ((I2C_MASTER_DMA_TX_ENABLED == 1) || (I2C_MASTER_DMA_RX_ENABLED == 1))
typedef struct I2C_MASTER_DMA_CONFIG
{
  const XMC_DMA_CH_CONFIG_t * dma_ch_config;   /**< Pointer to the DMA channel configuration.*/
  GLOBAL_DMA_t * global_dma;                   /**< Global DMA handle */
  uint8_t dma_channel;                         /**< DMA channel number */
} I2C_MASTER_DMA_CONFIG_t;
#endif
/**
 * @brief Constant structure for holding the configuration parameters of I2C channel.
 */
typedef struct I2C_MASTER_CONFIG
{
   const XMC_I2C_CH_CONFIG_t *brg_config;             /*!< Basic I2C configuration from the GUI with baud*/
#if (I2C_MASTER_DMA_TX_ENABLED == 1)
   const I2C_MASTER_DMA_CONFIG_t * const transmit_dma_config; /**< Pointer to the DMA channel configuration used for
                                                                   data transmission.*/
#endif
#if (I2C_MASTER_DMA_RX_ENABLED == 1)
   const I2C_MASTER_DMA_CONFIG_t * const receive_dma_config;  /**< Pointer to the DMA channel configuration used for
                                                                   data reception.*/
#endif
   i2c_master_fptr_cbhandler fptr_i2c_config;         /*!< Function pointer to configure the MUX values*/
   i2c_master_fptr_cbhandler fptr_i2c_enable_io;      /*!< Function pointer to enable SDA/SCL output pins*/
   i2c_master_fptr_cbhandler fptr_i2c_disable_io;     /*!< Function pointer to disable SDA/SCL output pins*/

   i2c_master_fptr_cbhandler tx_cbhandler;            /*!< Function pointer to hold the callback function pointer,
                                                           called when the transmission is complete*/
   i2c_master_fptr_cbhandler rx_cbhandler;            /*!< Function pointer to hold the callback function pointer,
                                                           called when the reception is complete*/
   i2c_master_fptr_cbhandler nack_cbhandler;          /*!< Function pointer to hold the callback function pointer,
                                                           called when nack is received*/
   i2c_master_fptr_cbhandler arbitration_cbhandler;   /*!< Function pointer to hold the callback function pointer,
                                                           called when arbitration lost is occured*/
   i2c_master_fptr_cbhandler error_cbhandler;         /*!< Function pointer to hold the callback function pointer,
                                                           called when error is detected.*/
   I2C_MASTER_TRANSFER_MODE_t transmit_mode;          /**< Mode used for transmitting data. Data can be transmitted using
                                                           interrupt, DMA or direct(using polling or external APP connection.)*/
   I2C_MASTER_TRANSFER_MODE_t receive_mode;           /**< Mode used for receiving data. Data can be received using
                                                           interrupt, DMA or direct(using polling or external APP connection.)*/

   XMC_USIC_CH_FIFO_SIZE_t txFIFO_size;               /*!< TxFIFO size configuration*/
   XMC_USIC_CH_FIFO_SIZE_t rxFIFO_size;               /*!< RxFIFO size configuration*/

   IRQn_Type tx_irqn;
   IRQn_Type rx_irqn; 
} I2C_MASTER_CONFIG_t;

/**
 * @brief Structure to hold the dynamic variables for the I2C_MASTER communication.
 */
typedef struct I2C_MASTER_RUNTIME
{
  uint8_t * tx_data;                     /*!< Pointer to the transmit data buffer*/
  uint8_t * rx_data;                     /*!< Pointer to the receive data buffer*/
  uint32_t tx_data_count;                /*!< Number of bytes of data to be transmitted*/
  volatile uint32_t tx_data_index;       /*!< Index to the byte to be transmitted next in the tx_data buffer*/
  uint32_t rx_data_count;                /*!< Number of bytes of data to be received*/
#if (I2C_MASTER_DMA_RX_ENABLED == 1)
  uint32_t rx_dma_data_count;            /*!< Number of bytes of data to be received-DMA mode*/
  uint32_t rx_dma_data_index;            /*!< Index of bytes of data to be received-DMA mode*/
#endif
  volatile uint32_t rx_data_index;       /*!< Indicates the number of bytes currently available in the rx_data buffer*/
  volatile uint32_t direction;           /*!< Indicates TRANSMIT/RECEIVE */
  uint32_t send_stop;                    /*!< Indicates to stop the I2C */
  uint32_t send_nack;                    /*!< Indicates to send nack */
  uint8_t tx_ack_sr;                         /*!< Service request number assigned to transmit interrupt*/
  uint8_t rx_sr;                         /*!< Service request number assigned to receive interrupts*/
  volatile bool tx_busy;                 /*!< Status flag to indicate busy when a transmission is assigned*/
  volatile bool rx_busy;                 /*!< Status flag to indicate busy when a reception is assigned*/
  volatile bool bus_acquired;            /*!< flag to indicate whether bus is acquired or not */
} I2C_MASTER_RUNTIME_t;


/**
 * @brief Handler structure with pointers to dynamic and static parameters.
 */
typedef struct I2C_MASTER
{
  XMC_USIC_CH_t *channel;                    /*!< USIC channel*/
  const I2C_MASTER_CONFIG_t * const config;  /*!< I2C configuration structure pointer*/
  I2C_MASTER_RUNTIME_t * const runtime;      /*!< Pointer to the structure holding all variables,
   	                                               that can change at runtime*/
} I2C_MASTER_t;

/**
 * @}
 */

#ifdef __cplusplus
extern "C" {
#endif


/**
 * @ingroup I2C_MASTER_apidoc
 * @{
 */

/***********************************************************************************************************************
 * API PROTOTYPES
 **********************************************************************************************************************/
/**
 * @brief Get I2C_MASTER APP version.
 * @return \a DAVE_APP_VERSION_t APP version information (major, minor and patch number)
 *
 * \par<b>Description: </b><br>
 * The function can be used to check application software compatibility with a
 * specific version of the APP.
 *
 * @code
 *  #include <DAVE.h>
 *
 *  int main(void)
 *  {
 *    DAVE_APP_VERSION_t version;
 *    DAVE_Init();
 *    version = I2C_MASTER_GetAppVersion();
 *    if(version.major != 4U)
 *    {
 *    }
 *    while(1)
 *    {}
 *    return 0;
 *  }
 * @endcode<BR> </p>
 */
DAVE_APP_VERSION_t I2C_MASTER_GetAppVersion(void);
/**
 * @brief This function initializes the I2C_MASTER APP based on user provided configuration.
 *
 * @return None
 *
 * \par<b>Description: </b><br>
 * I2C configurations like channel selection,baud rate setting,
 * FIFO configuration etc are done in this API.
 * Protocol specific interrupts can also be enabled using the I2C_MASTER_Init
 * function.
 *
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 * @code
 *
 *  #include <DAVE.h>
 *  int main(void)
 *  {
 *   // Initializing the modules and the multiplexer
 *   DAVE_Init(); // I2C_MASTER_Init will be called from DAVE_Init()
 *   while(1)
 *   {}
 *   return 0;
 *  }
 * @endcode<BR> </p>
 *
 */

I2C_MASTER_STATUS_t I2C_MASTER_Init(const I2C_MASTER_t *const handle);


/**
 * @brief  Receives the data from I2C slave device.
 * @param  handle I2C device handle of type I2C_MASTER_t*
 * @param  send_start Flag to indicate that the start condition need to be send.
 * @param  address I2C slave device address.
 * @param  data buffer to receive data.
 * @param  count The number of bytes to be received from slave.
 * @param  send_stop The flag to indicate that the stop condition need to be send.
 * @param  send_nack The flag to indicate that the NACK condition need to be send for the last byte of data.
 * @return @ref I2C_MASTER_STATUS_t Status.
 * \par<b>NOTE: </b><br>
 * I2C_MASTER_Receive API can be used in Interrupt and Direct modes.\n
 * Address(address) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write).\n
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 *
 * @code
 *
 *  #include <DAVE.h>
 *  #define SLAVE_ADDRESS 0xA0
 *  #define BYTES_TO_READ 10
 *  #define BYTES_TO_TRANSMIT 10
 *
 *  typedef enum PCA9502_REGADDR {
 *    IO_DIR    = 0xA << 3,
 *    IO_STATE  = 0xB << 3,
 *    IO_INTE   = 0xC << 3,
 *    IO_CTRL   = 0xE << 3
 *  } PCA9502_REGADDR_t;

 *  uint8_t mem_address[2];
 *  uint8_t data = 0x55;
 *  uint8_t rx_data;
 *
 *  int main(void)
 *  {
 *   DAVE_STATUS_t init_status;  
 *   init_status = DAVE_Init();
 *   if(init_status == DAVE_STATUS_SUCCESS)
 *   {
 *     mem_address[0] = IO_STATE;//memory which need to be read from slave
 *     //Write data to IO EXPANDER
 *     I2C_MASTER_Transmit(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *     I2C_MASTER_Transmit(&I2C_MASTER_0,false,SLAVE_ADDRESS,&data,1,true);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));

 *     //Read data from IO EXPANDER
 *     I2C_MASTER_Transmit(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *     I2C_MASTER_Receive(&I2C_MASTER_0,true,SLAVE_ADDRESS,&rx_data,1,true,true);
 *     while(I2C_MASTER_IsRxBusy(&I2C_MASTER_0));
 *   }
 *   while(1)
 *   { }
 *  return 0;
 * }
 *
 * @endcode<BR> </p>
 *
 */
I2C_MASTER_STATUS_t I2C_MASTER_Receive(I2C_MASTER_t *handle, bool send_start, const uint32_t address,
                                       uint8_t * data, const uint32_t count, bool send_stop, bool send_nack);

/**
 * @brief Transmits data to I2C slave device.
 *
 * @param  handle I2C device handle of type I2C_MASTER_t*
 * @param  send_start The flag to indicate that the start condition need to be send.
 * @param  address I2C slave device address.
 * @param  data buffer containing the data to transmit.
 * @param  size The number of bytes to be send to slave.
 * @param  send_stop The flag to indicate that the stop condition need to be send.
 *
 * @return @ref I2C_MASTER_STATUS_t Status.
 * \par<b>NOTE: </b><br>
 * I2C_MASTER_Transmit API can be used in Interrupt and Direct modes.\n
 * Address(address) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write). \n
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 * 
 * @code
 *
 *  #include <DAVE.h>
 *  #define SLAVE_ADDRESS (0xA0)
 *  typedef enum PCA9502_REGADDR {
 *    IO_DIR    = 0xA << 3,
 *    IO_STATE  = 0xB << 3,
 *    IO_INTE   = 0xC << 3,
 *    IO_CTRL   = 0xE << 3
 *  } PCA9502_REGADDR_t;
 *
 *  uint8_t tx_buffer[64] = {0x01,0x02,0x03,0x04,0x05};
 *  uint8_t mem_address[2];
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      mem_address[0] = IO_STATE;//memory which need to be read from slave
 *      //Write data to IO EXPANDER
 *      I2C_MASTER_Transmit(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *      I2C_MASTER_Transmit(&I2C_MASTER_0,false,SLAVE_ADDRESS,tx_buffer,5,true);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *    }
 *    while(1)
 *    { }

 *   return 0;
 * }
 *
 * @endcode<BR> </p>
 *
 */
I2C_MASTER_STATUS_t I2C_MASTER_Transmit(I2C_MASTER_t *handle, bool send_start, const uint32_t address,
		                                uint8_t *data, const uint32_t size, bool send_stop);

/**
 * @brief Get the I2C flag status.
 *
 * @param  handle I2C device handle of type I2C_MASTER_t*
 * @param  flagtype   single or multiple flags, whose status need to be checked.
 *			 	      bitwise OR operation on elements of enum XMC_I2C_CH_STATUS_FLAG_t can be used to select
 *                    multiple flags.
 *
 * @return uint32_t Flag status.
 *
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 *
 * @code
 *
 *  #include <DAVE.h>
 *
 *  #define SLAVE_ADDRESS (0xA0)
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *    }
 *    while(1)
 *    {}
 *
 *   return 0;
 *  }
 *
 * @endcode<BR> </p>
 *
 */
uint32_t I2C_MASTER_GetFlagStatus(const I2C_MASTER_t *handle, uint32_t flagtype);

/**
 * @brief Clear the I2C flag status.
 *
 * @param  handle I2C device handle of type I2C_MASTER_t*
 * @param  flagtype   single or multiple flags, whose status need to be checked.
 *                    The bitwise OR operation on elements of enum XMC_I2C_CH_STATUS_FLAG_t can be used to select
 *                    multiple flags.
 *
 * @return None <BR>
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 * @code
 *
 *  #include <DAVE.h>
 *
 *  #define SLAVE_ADDRESS (0xA0)
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *    }
 *    while(1)
 *    {}
 *
 *   return 0;
 * }
 * @endcode<BR> </p>
 *
 */
void I2C_MASTER_ClearFlag(const I2C_MASTER_t *handle, uint32_t flagtype);

/**
 * @brief Aborts the ongoing data transmission.
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return I2C_MASTER_STATUS_t status
 *
 * \par<b>Description:</b><br>
 * If there is a transmission in progress, it will be stopped. Once the transmission is stopped, 
 * user can start a new transmission without delay.
 *
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 *
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t tx_buf[50] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_Transmit(&I2C_MASTER_0, true, SLAVE_ADDRESS, &tx_buf[0], 16, true);
 *      I2C_MASTER_AbortTransmit(&I2C_MASTER_0);
 *      I2C_MASTER_SendStop(&I2C_MASTER_0);
 *      I2C_MASTER_Transmit(&I2C_MASTER_0, true, SLAVE_ADDRESS, &tx_buf[0], 16, true);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *    }
 *    while(1U)
 *    {
 *    }
 *
 *    return 1U;
 *  }
 *
 * @endcode
 *
 */
I2C_MASTER_STATUS_t I2C_MASTER_AbortTransmit(const I2C_MASTER_t *const handle);

/**
* @brief Stops the active data reception request.
 * @param handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return I2C_MASTER_STATUS_t status
 *
 * \par<b>Description:</b><br>
 * If a reception is in progress, it will be stopped. When a reception request
 * is active, user will not be able to place a new receive request till the active
 * reception is complete. This API can stop the progressing reception to make
 * a new receive request.
 *
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  int main(void)
 *  {
 *   uint8_t rx_buf[25];
 *   uint8_t tx_buf[2];
 *   DAVE_STATUS_t init_status;
 *   init_status = DAVE_Init();
 *   if(init_status == DAVE_STATUS_SUCCESS)
 *   {
 *     //send the address from which data to be transfered
 *     tx_buf[0] = 0;
 *     I2C_MASTER_Transmit(&I2C_MASTER_0, true, SLAVE_ADDRESS, &tx_buf[0], 1, false);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *     I2C_MASTER_Receive(&I2C_MASTER_0, true, SLAVE_ADDRESS, &rx_buf[0], 16, true, true);
 *     I2C_MASTER_AbortReceive(&I2C_MASTER_0);
 *     I2C_MASTER_SendStop(&I2C_MASTER_0);
 *     I2C_MASTER_Transmit(&I2C_MASTER_0, true, SLAVE_ADDRESS, &tx_buf[0], 1, false);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *     I2C_MASTER_Receive(&I2C_MASTER_0, true, SLAVE_ADDRESS, &rx_buf[0], 16, true, true);
 *     while(I2C_MASTER_IsRxBusy(&I2C_MASTER_0));
 *   }
 *   while(1U)
 *   {
 *   }
 *
 *   return 1U;
 * }
 *
 * @endcode
 *
 */
I2C_MASTER_STATUS_t I2C_MASTER_AbortReceive(const I2C_MASTER_t *const handle);


#if (I2C_MASTER_DMA_TX_ENABLED == 1U)
/**
 * @brief Registers a request for transmitting data over I2C channel using DMA.
 *
 * @param  handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  block_size size of the block
 * @param  addr    address\n
 * \b Range: minimum= 1, maximum= 4095.
 *
 * @return  I2C_MASTER_STATUS_t: Status of transmit request.\n
 *                        @ref I2C_MASTER_STATUS_SUCCESS if the request is accepted.\n
 *                        @ref I2C_MASTER_STATUS_BUSY if a transmission is in progress.\n
 *
 * <i>Imp Note:</i> Return value should be validated by user to ensure that the
 * request is registered.
 *
 * \par<b>Description:</b><br>
 * The data transmission is accomplished using DMA. User can configure a callback function in the APP UI. 
 * When the data is fully transmitted, the callback function will be executed. The function uses APP handle's runtime 
 * structure to store the status of transmission.
 * This function only registers a data transmission request, if there is no active transmission in progress. 
 * Actual data transmission happens through DMA channel.
 * A maximum of 4095 bytes can be transmitted in one API call. This limit is because of the DMA single block size.
 * Callback function is executed when all the data bytes are transmitted.
 * If a callback function is not configured, user has to poll for the value of \a tx_busy flag of
 * the APP handle structure( \a handle->runtime->tx_busy ) to check for
 * the completion of data transmission.
 * If data more than the block size of 4095 have to be transmitted, user will have to transmit them using multiple
 * calls to this API.
 * \par<b>NOTE: </b><br>
 * I2C_MASTER_StartTransmitDMA API can be used in DMA mode.
 * Transmit should be configured as "DMA" mode in advanced settings tab. \n
 * Address(addr) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write).<br>
 * Example Usage:
 *
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t Send_Data[] = "Infineon Technologies";
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *	    while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *	    {
 *	      // wait for ACK
 *	    }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      // write to address 0
 *      I2C_MASTER_TransmitByte(&I2C_MASTER_0, 0x00);
 *	    while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *	    {
 *	      // wait for ACK
 *	    }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      // trigger the DMA
 *      I2C_MASTER_StartTransmitDMA(&I2C_MASTER_0, sizeof(Send_Data), Send_Data);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 * }
 * @endcode
 *
 */
I2C_MASTER_STATUS_t I2C_MASTER_StartTransmitDMA(const I2C_MASTER_t *const handle, uint32_t block_size, uint8_t *addr);
#endif

#if (I2C_MASTER_DMA_RX_ENABLED == 1U)
/**
 * @brief Registers a request for receiving data over I2C_MASTER channel using DMA.
 *
 *
 * @param  handle  Pointer to I2C_MASTER_t handle structure
 * @param block_size  size of the block
 * @param  addr  address \n
 * \b Range: minimum= 1, maximum= 4095.
 *
 * @return  I2C_MASTER_STATUS_t: Status for receive request.\n
 *                        @ref I2C_MASTER_STATUS_SUCCESS if the request is accepted.\n
 *                        @ref I2C_MASTER_STATUS_BUSY if a reception is in progress.\n
 *
 * \par<b>Description:</b><br>
 * Data will be received asynchronously. When the requested number of data bytes are received, optionally, the user
 * configured callback function will be executed.
 * This function only registers a request to receive a number of data bytes from a USIC channel.
 * When all the requested number of data bytes are received, the configured callback function will be executed.
 * If a callback function is not configured, the user has to poll for the value of the variable, \a
 * handle->runtime->rx_busy to be false. The value is updated to \a false when all the requested number of data bytes
 * are received.
 * A maximum of 4095 bytes can be received in one API call. This limit is because of the DMA single block size.
 *
 * \par<b>NOTE: </b><br>: I2C_MASTER_StartReceiveDMA API can be used only in DMA mode
 * Receive should be configured as "DMA" mode in advanced settings tab \n
 * Address(addr) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write).<br>
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  //Pre condition:
 *  //Transmit mode and receive mode should be configured to "DMA" in advanced settings tab
 *
 *  uint8_t ReadData[256];
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *	    while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *	    {
 *	      // wait for ACK
 *	    }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      // write to address 0
 *      I2C_MASTER_TransmitByte(&I2C_MASTER_0, 0x00);
 *	    while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *	    {
 *	      // wait for ACK
 *	    }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      I2C_MASTER_SendRepeatedStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_READ);
 *	    while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *	    {
 *	      // wait for ACK
 *	    }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 
 *      I2C_MASTER_StartReceiveDMA(&I2C_MASTER_0, 200, ReadData);
 *      while(I2C_MASTER_IsRxBusy(&I2C_MASTER_0));
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 *  @endcode
 *
 */
I2C_MASTER_STATUS_t I2C_MASTER_StartReceiveDMA(const I2C_MASTER_t *const handle, uint32_t block_size, uint8_t *addr);
#endif

#if (I2C_MASTER_INTERRUPT_TX_ENABLED == 1U)
/**
 * @brief Registers a request for transmitting data over I2C_MASTER channel.
 *
 * @param  handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  send_start flag to indicate the start condition
 * @param  address slave address
 * @param  data    pointer to buffer
 * @param  size    number of bytes
 * @param  send_stop flag to indicate the stop condition\n
 * \b Range: minimum= 1, maximum= maximum supported by uint32_t.
 *
 * @return  I2C_MASTER_STATUS_t: Status of transmit request.\n
 *                        @ref I2C_MASTER_STATUS_SUCCESS if the request is accepted.\n
 *                        @ref I2C_MASTER_STATUS_BUSY if a transmission is in progress.\n
 *
 * <i>Imp Note:</i> Return value should be validated by user to ensure that the
 * request is registered.
 *
 * \par<b>Description:</b><br>
 * The data transmission is accomplished using transmit interrupt. User can configure a callback function in the APP UI.
 * When the data is fully transmitted, the callback function will be executed. If transmit FIFO is enabled, 
 * the trigger limit is set to 1. So the transmit interrupt will be generated when all the data in FIFO is moved 
 * from FIFO. The function uses APP handle's runtime structure to store the data pointer, count, data index and 
 * status of transmission. This function only registers a data transmission request if there is no active transmission 
 * in progress.
 * Actual data transmission happens in the transmit interrupt service routine. A trigger is generated for the transmit
 * interrupt to start loading the data. If transmit FIFO is configured, the data is filled into the FIFO.
 * Transmit interrupt will be generated next time when the transmit FIFO is empty. At this point of time, if there is
 * some more data to be transmitted, it is loaded to the FIFO again. When FIFO is not enabled, data is transmitted one
 * byte at a time. On transmission of each byte an interrupt is generated and the next byte is transmitted in the
 * interrupt service routine. Callback function is executed when all the data bytes are transmitted.
 * If a callback function is not configured, user has to poll for the value of \a tx_busy flag of the APP handle
 * structure( \a handle->runtime->tx_busy ) to check for the completion of data transmission.<br>
 * \par<b>NOTE: </b><br>: I2C_MASTER_StartTransmitIRQ API can be used only in Interrupt mode.
 * Transmit should be configured as "Interrupt" mode in advanced settings tab.\n
 * Address(address) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write).
 *
 * @code
 *
 *  #include <DAVE.h>
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t tx_buffer[64] = {0x01,0x02,0x03,0x04,0x05};
 *  uint8_t mem_address[2];
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      mem_address[0] = 0x00;//memory which need to be read from slave
 *      //Write data to IO EXPANDER
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,false,SLAVE_ADDRESS,tx_buffer,64,true);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *    }
 *    while(1)
 *    { }

 *    return 0;
 *  }
 *
 * @endcode<BR> </p>
 *
 */

I2C_MASTER_STATUS_t I2C_MASTER_StartTransmitIRQ(I2C_MASTER_t *handle, bool send_start, const uint32_t address,
                                                uint8_t *data, const uint32_t size, bool send_stop);
#endif
#if (I2C_MASTER_INTERRUPT_RX_ENABLED == 1U)
/**
 * @brief Registers a request for receiving data over I2C_MASTER channel.
 *
 *
 * @param  handle  Pointer to I2C_MASTER_t handle structure
 * @param  send_start flag to indicate the start condition
 * @param  address slave address
 * @param  data    pointer to buffer
 * @param  count    number of bytes
 * @param  send_stop flag to indicate the stop condition
 * @param  send_nack flag to indicate the nack condition\n
 * \b Range: minimum= 1, maximum= maximum value supported by type uint32_t.
 *
 * @return  I2C_MASTER_STATUS_t: Status for receive request.\n
 *                        @ref I2C_MASTER_STATUS_SUCCESS if the request is accepted.\n
 *                        @ref I2C_MASTER_STATUS_BUSY if a reception is in progress.\n
 *
 *
 * \par<b>Description:</b><br>
 * Data will be received asynchronously. When the requested number of data bytes are received, optionally, the user
 * configured callback function will be executed. Based on the UI configuration, either standard receive buffer or
 * receive FIFO is used for data reception. An interrupt is configured for reading received data from the bus. This
 * function only registers a request to receive a number of data bytes from a USIC channel. If FIFO is configured for
 * reception, the FIFO limit is dynamically configured to optimally utilize the CPU load.  When all the requested number
 * of data bytes are received, the configured callback function will be executed. If a callback function is not
 * configured, the user has to poll for the value of the variable, \a handle->runtime->rx_busy to be false. The value
 * is updated to \a false when all the requested number of data bytes are received.<br>
 * \par<b>NOTE: </b><br>: I2C_MASTER_StartReceiveIRQ API can be used only in Interrupt mode.
 * Receive should be configured as "Interrupt" mode in advanced settings tab.\n
 * Address(address) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write).
 *
 * @code
 *
 *  #include <DAVE.h>
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t rx_buffer[64];
 *  uint8_t mem_address[2];
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      mem_address[0] = 0x00;//memory which need to be read from slave
 *     //Write data to IO EXPANDER
 *     I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *     I2C_MASTER_StartReceiveIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,rx_buffer,64,true, true);
 *     while(I2C_MASTER_IsRxBusy(&I2C_MASTER_0));
 *    }
 *    while(1)
 *    { }
 *    return 0;
 *  }
 *
 * @endcode<BR> </p>
 *
 */
 I2C_MASTER_STATUS_t I2C_MASTER_StartReceiveIRQ(I2C_MASTER_t *handle, bool send_start, const uint32_t address,
                                               uint8_t * data, const uint32_t count, bool send_stop, bool send_nack);
#endif


/**
 * @brief Gets the transmit FIFO event flags.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 *
 * @return uint32_t: Status of the STBI and TBERI bits in TRBSR register in
 *                      their bit positions.\n
 *                      \b Range: Use type @ref XMC_USIC_CH_TXFIFO_EVENT_t for the bitmask of events.
 *
 * \par<b>Description:</b><br>
 * Function reads the value of TRBSR register. It masks the standard transmit buffer interrupt flag and transmit
 * buffer error flag before providing the value.
 * User has to mask the bits of interest before checking the status.
 * \par<b>NOTE: </b><br>: Enable transmit fifo in Advanced settings tab. <br>
 * Example Usage:
 *
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t mem_address[2];
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      mem_address[0] = 0x00;//memory which need to be read from slave
 *      //Configure transmit fifo trigger limit as 10
 *      I2C_MASTER_SetTXFIFOTriggerLimit(&I2C_MASTER_0, 16, 10);
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,16,false);
 *      //Wait for FIFO transmit standard buffer interrupt to fill it again with remaining data
 *      while((I2C_MASTER_GetTXFIFOStatus(&I2C_MASTER_0) & XMC_USIC_CH_TXFIFO_EVENT_STANDARD) == 0);
 *      I2C_MASTER_ClearTXFIFOStatus(&I2C_MASTER_0, XMC_USIC_CH_TXFIFO_EVENT_STANDARD);
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,6,false);
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 * @endcode
 *
 */
__STATIC_INLINE uint32_t I2C_MASTER_GetTXFIFOStatus(const I2C_MASTER_t* const handle)
{
  XMC_ASSERT("I2C_MASTER_GetTXFIFOStatus: invalid handle", (handle != NULL))
  return XMC_USIC_CH_TXFIFO_GetEvent(handle->channel);
}

/**
 * @brief Configures trigger limit for the transmit FIFO.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  size   FIFO size
 * @param  limit Value of transmit FIFO filling level, transition below which the interrupt should be generated.\n
 *               \bRange: 0 to transmit FIFO size.\n
 *               e.g, If transmit FIFO size is 16, and limit is configured as 8, FIFO standard transmit buffer interrupt
 *               will be generated when the FIFO filling level drops from 8 to 7.\n
 *
 * @return None\n
 *
 * \par<b>Description:</b><br>
 * Transmit FIFO trigger limit is configured by setting its value in the TBCTR register.
 * Transmit FIFO is configured to generate interrupt when the FIFO filling level drops
 * below the trigger limit.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t Send_Data[] = "Infineon Technologies";
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      //Configure transmit fifo trigger limit, draining level as 10
 *      I2C_MASTER_SetTXFIFOTriggerLimit(&I2C_MASTER_0, 16, 10);
 *      // Execution will happen two times in the interrupt handler as the limit is set to 10
 *      I2C_MASTER_Transmit(&I2C_MASTER_0, true, SLAVE_ADDRESS, Send_Data, 16, true);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 *
 * @endcode
 */
__STATIC_INLINE void I2C_MASTER_SetTXFIFOTriggerLimit(I2C_MASTER_t * const handle, const uint32_t size,
		                                              const uint32_t limit)
{
  XMC_ASSERT("I2C_MASTER_SetTXFIFOTriggerLimit: invalid handle", (handle != NULL))
  XMC_USIC_CH_TXFIFO_SetSizeTriggerLimit(handle->channel, (XMC_USIC_CH_FIFO_SIZE_t)size, limit);
}
/**
 * @brief Configures trigger limit for the receive FIFO.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  size   FIFO size
 * @param  limit Value of receive FIFO filling level, transition above which the interrupt should be generated.\n
 *               \bRange: 0 to receive FIFO size.\n
 *               e.g, If receive FIFO size is 16, and limit is configured as 8, FIFO receive buffer interrupt
 *               will be generated when the FIFO filling level rises from 8 to 9.\n
 *
 * @return None\n
 *
 * \par<b>Description:</b><br>
 * Receive FIFO trigger limit is configured by setting its value in the RBCTR register.
 * Receive FIFO is configured to generate interrupt when the FIFO filling level rises
 * above the trigger limit.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *
 *  #define SLAVE_ADDRESS 0xA0
 *
 *  uint8_t Rx_Data[256];
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      //Configure receive fifo trigger limit to filling level as 10
 *      I2C_MASTER_SetRXFIFOTriggerLimit(&I2C_MASTER_0, 16, 10);
 *      // Execution will happen two times in the receive interrupt handler as the limit is set to 10
 *      I2C_MASTER_Receive(&I2C_MASTER_0, true, SLAVE_ADDRESS, Rx_Data, 16, true, true);
 *      while(I2C_MASTER_IsRxBusy(&I2C_MASTER_0));
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 *
 * @endcode
 */
__STATIC_INLINE void I2C_MASTER_SetRXFIFOTriggerLimit(I2C_MASTER_t * const handle, const uint32_t size,
		                                              const uint32_t limit)
{
  XMC_ASSERT("I2C_MASTER_SetRXFIFOTriggerLimit: invalid handle", (handle != NULL))
  XMC_USIC_CH_RXFIFO_SetSizeTriggerLimit(handle->channel, (XMC_USIC_CH_FIFO_SIZE_t)size, limit);
}

/**
 * @brief Checks if the transmit FIFO is full.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 *
 * @return bool Status of transmit FIFO filling level.
 *              \bRange: \atrue- if transmit FIFO is full.<br>
 *                       \afalse- if transmit FIFO is not full.<br>
 * \par<b>Description:</b><br>
 * Checks the status using the register TRBSR. Can be used while filling
 * data to the transmit FIFO.
 * \par<b>NOTE: </b><br>: Transmit should be "Direct" mode in advanced settings tab.<br>
 * Example Usage:
 *
 * @code
 *
 *  #include <DAVE.h>                 //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0

 *
 *  uint8_t send_data[] = "Infineon Technologies";
 *  int main(void)
 *  {
 *    DAVE_STATUS_t status;
 *    status = DAVE_Init();           // Initialization of DAVE APPs
 *
 *    if(status == DAVE_STATUS_FAILURE)
 *    {
 *      XMC_DEBUG("DAVE APPs initialization failed\n");
 *
 *      while(1U)
 *      {
 *      }
 *  }
 *  I2C_MASTER_Transmit(&I2C_MASTER_0, true, SLAVE_ADDRESS, &send_data[0], 10, false);
 *  //Wait when Tx FIFO is full
 *  while(!I2C_MASTER_IsTXFIFOFull(&I2C_MASTER_0))
 *  {
 *    I2C_MASTER_Transmit(&I2C_MASTER_0, false, SLAVE_ADDRESS, &send_data[0], 10, false);
 *  }
 *  while(1U)
 *  {
 *  }
 * }
 * @endcode
 */
__STATIC_INLINE bool I2C_MASTER_IsTXFIFOFull(const I2C_MASTER_t* const handle)
{
  XMC_ASSERT("I2C_MASTER_IsTXFIFOFull: invalid handle", (handle != NULL))
  return XMC_USIC_CH_TXFIFO_IsFull(handle->channel);
}

/**
 * @brief Checks if the receive FIFO is empty.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 *
 * @return bool Status of receive FIFO filling level.
 *              \bRange: \atrue- if receive FIFO is empty.<br>
 *                       \afalse- if receive FIFO still has data.<br>
 * \par<b>Description:</b><br>
 * Checks the status using the register TRBSR. Can be used while reading data from the receive FIFO.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>                 //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS (0xA0)
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    uint8_t rec_data[64];
 *    uint8_t index = 0, loc_index = 0;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      // write to address 0
 *      I2C_MASTER_TransmitByte(&I2C_MASTER_0, 0x00);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      I2C_MASTER_SendRepeatedStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_READ);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      while(index < 16)
 *      {
 *        I2C_MASTER_ReceiveACK(&I2C_MASTER_0);
 *        index++;
 *      }
 *      //Wait when Rx FIFO is empty
 *      while(!I2C_MASTER_IsRXFIFOEmpty(&I2C_MASTER_0))
 *      {
 *        rec_data[loc_index++] = I2C_MASTER_GetReceivedByte(&I2C_MASTER_0);
 *      }
 *    }
 *   while(1U)
 *   {
 *   }
 *  }
 * @endcode
 */
__STATIC_INLINE bool I2C_MASTER_IsRXFIFOEmpty(const I2C_MASTER_t* const handle)
{
  XMC_ASSERT("I2C_MASTER_IsRXFIFOEmpty: invalid handle", (handle != NULL))
  return XMC_USIC_CH_RXFIFO_IsEmpty(handle->channel);
}

/**
 * @brief Gets the status of event flags related to receive FIFO.
 *
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 *
 * @return uint32_t: Status of standard receive buffer event, alternative receive buffer event and receive buffer
 * error event in their bit positions in TRBSR register.\n
 * \b Range: Use type @ref XMC_USIC_CH_RXFIFO_EVENT_t for event bitmasks. Multiple events' status can be combined for
 * comparison using \a OR operation.
 *
 * \par<b>Description:</b><br>
 * It provides the status of standard receive buffer event, alternative receive buffer event and receive buffer error
 * event.
 * Function masks the TRBSR register with the bitmask of SRBI, ARBI and RBERI flags. User has to mask the bits of
 * interest before checking the status.
 *
 * Example Usage:
 * @code
 *
 *   #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *   #define SLAVE_ADDRESS 0xA0
 *   uint8_t mem_address[2];
 *   int main(void)
 *   {
 *     DAVE_STATUS_t init_status;
 *
 *     init_status = DAVE_Init();
 *     if(init_status == DAVE_STATUS_SUCCESS)
 *     {
 *       mem_address[0] = 0x00;//memory which need to be read from slave
 *       //Configure receive fifo trigger limit as 10
 *       I2C_MASTER_SetRXFIFOTriggerLimit(&I2C_MASTER_0, 16, 10);
 *       I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *       while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *       I2C_MASTER_StartReceiveIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,16,true, true);
 *       //Wait for FIFO transmit standard buffer interrupt to fill it again with remaining data
 *       while((I2C_MASTER_GetRXFIFOStatus(&I2C_MASTER_0) & XMC_USIC_CH_RXFIFO_EVENT_STANDARD) == 0);
 *       I2C_MASTER_ClearRXFIFOStatus(&I2C_MASTER_0, XMC_USIC_CH_RXFIFO_EVENT_STANDARD);
 *       I2C_MASTER_StartReceiveIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,6,false, false);
 *     }
 *     else
 *     {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *     }
 *      return 1U;
 *   }
 * @endcode
 *
 */
__STATIC_INLINE uint32_t I2C_MASTER_GetRXFIFOStatus(const I2C_MASTER_t* const handle)
{
  XMC_ASSERT("I2C_MASTER_GetRXFIFOStatus: invalid handle", (handle != NULL))
  return XMC_USIC_CH_RXFIFO_GetEvent(handle->channel);
}

/**
 * @brief Function clears the specified FIFO event flag related to
 * transmit FIFO.
 *
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  flag Value with event bits at their bit positions in TRBSR register to be cleared.\n
 *             \b Range: Use type @ref XMC_USIC_CH_TXFIFO_EVENT_t. Multiple events can be combined using
 *             \a OR operation.
 *
 * @return    None
 *
 * \par<b>Description:</b><br>
 * Function clears a status bit in TRBSR register using the TRBSCR register. But the function does not mask the input
 * value with the bit positions restricted to transmit FIFO status bits. User should ensure that the input value is
 * appropriately masked.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t mem_address[2];
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      mem_address[0] = 0x00; //memory which need to be read from slave
 *      //Configure transmit fifo trigger limit as 10
 *      I2C_MASTER_SetTXFIFOTriggerLimit(&I2C_MASTER_0, 16, 10);
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,16,false);
 *      //Wait for FIFO transmit standard buffer interrupt to fill it again with remaining data
 *      while((I2C_MASTER_GetTXFIFOStatus(&I2C_MASTER_0) & XMC_USIC_CH_TXFIFO_EVENT_STANDARD) == 0);
 *      I2C_MASTER_ClearTXFIFOStatus(&I2C_MASTER_0, XMC_USIC_CH_TXFIFO_EVENT_STANDARD);
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,6,false);
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 * @endcode
 *
 */
__STATIC_INLINE void I2C_MASTER_ClearTXFIFOStatus(const I2C_MASTER_t* const handle, const uint32_t flag)
{
  XMC_ASSERT("I2C_MASTER_ClearTXFIFOStatus: invalid handle", (handle != NULL))
  XMC_USIC_CH_TXFIFO_ClearEvent(handle->channel, flag);
}

/**
 * @brief Function clears the specified FIFO event flag related to receive FIFO. It should be used to clear the status
 * of standard receive buffer interrupt, alternative receive buffer interrupt and receive buffer error interrupt flags.
 *
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  flag Value with event bits at the bit positions in TRBSR register to be cleared.\n
 *             \b Range: Use type @ref XMC_USIC_CH_RXFIFO_EVENT_t for providing events.
 *             Multiple events can be input by using \a OR operation.
 *
 * @return    None
 *
 * \par<b>Description:</b><br>
 * Function clears a status bit in TRBSR using the TRBSCR register.
 * The function does not mask the input value to clear only receive buffer
 * events. So user should appropriately mask the input value before calling
 * the function.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  uint8_t mem_address[2];
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      mem_address[0] = 0x00;//memory which need to be read from slave
 *      //Configure receive fifo trigger limit as 10
 *      I2C_MASTER_SetRXFIFOTriggerLimit(&I2C_MASTER_0, 16, 10);
 *      I2C_MASTER_StartTransmitIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *      I2C_MASTER_StartReceiveIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,16,true, true);
 *      //Wait for FIFO transmit standard buffer interrupt to fill it again with remaining data
 *      while((I2C_MASTER_GetRXFIFOStatus(&I2C_MASTER_0) & XMC_USIC_CH_RXFIFO_EVENT_STANDARD) == 0);
 *      I2C_MASTER_ClearRXFIFOStatus(&I2C_MASTER_0, XMC_USIC_CH_RXFIFO_EVENT_STANDARD);
 *      I2C_MASTER_StartReceiveIRQ(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,6,false, false);
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 * @endcode
 *
 */
__STATIC_INLINE void I2C_MASTER_ClearRXFIFOStatus(const I2C_MASTER_t* const handle, const uint32_t flag)
{
  XMC_ASSERT("I2C_MASTER_ClearRXFIFOStatus: invalid handle", (handle != NULL))
  XMC_USIC_CH_RXFIFO_ClearEvent(handle->channel, flag);
}

/**
 * @brief Provides the received data from receive buffer.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return uint8_t: Data read from RBUF.\n
 *
 * \par<b>Description:</b><br>
 * This can be used in receive mode "Direct" to read the received data.
 * If Rx FIFO is not configured, function reads the value of RBUF register.
 * Otherwise it reads the data from OUTR register.
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    uint8_t rec_data[10];
 *    uint8_t index = 0,loc_index = 0;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      // write to address 0
 *      I2C_MASTER_TransmitByte(&I2C_MASTER_0, 0x00);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      I2C_MASTER_SendRepeatedStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_READ);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *        // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      while(index < 16)
 *      {
 *        I2C_MASTER_ReceiveACK(&I2C_MASTER_0);
 *         index++;
 *      }
 *      //Wait when Rx FIFO is empty
 *      while(!I2C_MASTER_IsRXFIFOEmpty(&I2C_MASTER_0))
 *      {
 *        rec_data[loc_index++] = I2C_MASTER_GetReceivedByte(&I2C_MASTER_0);
 *      }
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 * @endcode
 *
 */
/* Wrapper to the LLD API for reading back the value of the RBUF or OUTR register */
__STATIC_INLINE uint8_t I2C_MASTER_GetReceivedByte(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_GetReceivedByte: invalid handle", (handle != NULL))
  return (uint8_t)XMC_I2C_CH_GetReceivedData(handle->channel);
}

/**
 * @brief Transmits single byte using I2C protocol.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  byte data byte to transmit. \n
 * @return None\n
 * 
 * Example Usage:
 *
 * @code
 *
 *  #include <DAVE.h>                 //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t status;
 *
 *    status = DAVE_Init();
 *
 *    if(status == DAVE_STATUS_FAILURE)
 *    {
 *      XMC_DEBUG("DAVE APPs initialization failed\n");
 *
 *      while(1U)
 *      {
 *
 *      }
 *    }
 *    I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *    while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *    {
 *      // wait for ACK
 *    }
 *    I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *    I2C_MASTER_TransmitByte(&I2C_MASTER_0, 0x00);
 *    while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *    {
 *      // wait for ACK
 *    }
 *    I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *    while(1U)
 *    {
 *    }
 *  }
 * @endcode
 */
__STATIC_INLINE void I2C_MASTER_TransmitByte(I2C_MASTER_t * const handle, uint8_t byte)
{
  XMC_ASSERT("I2C_MASTER_TransmitByte: invalid handle", (handle != NULL))
  XMC_I2C_CH_MasterTransmit(handle->channel, byte);
}
/**
 * @brief Enables the selected protocol events for interrupt generation.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  event  Protocol events to be enabled for interrupt generation. \n
 *         \bRange: Use type \aXMC_I2C_CH_EVENT_t to select the event. Multiple events can be
 *         combined using the bitwise OR operation.\n
 * @return None\n
 *
 * \par<b>Description:</b><br>
 * Enables the events by configuring CCR or PCR register based on the event.
 * When the event is enabled, an interrupt can be generated on occurrence of the event.
 * The API should be used only for \a Direct mode related events. Using this API for non \a Direct mode
 * may not yield expected result.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>                 //Declarations from DAVE Code Generation (includes SFR declaration)
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t status;
 *
 *    status = DAVE_Init();
 *
 *    if(status == DAVE_STATUS_FAILURE)
 *    {
 *      XMC_DEBUG("DAVE APPs initialization failed\n");
 *
 *      while(1U)
 *      {
 *
 *      }
 *    }
 *    I2C_MASTER_EnableEvent(&I2C_MASTER_0, XMC_I2C_CH_EVENT_NACK);
 *    while(1U)
 *    {
 *    }
 *  }
 * @endcode
 */
__STATIC_INLINE void I2C_MASTER_EnableEvent(I2C_MASTER_t * const handle, uint32_t event)
{
  XMC_ASSERT("I2C_MASTER_EnableEvent: invalid handle", (handle != NULL))
  XMC_I2C_CH_EnableEvent(handle->channel, event);
}
/**
 * @brief Disables selected events from generating interrupt.
 *
 * @param  handle I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param  event  Events to be disabled from generating interrupt. \n
 *         \bRange: Use type \aXMC_I2C_CH_EVENT_t to select the event. Multiple events can be
 *         combined using the bitwise OR operation.\n
 * @return None
 *
 * \par<b>Description:</b><br>
 * Events are disabled by clearing their respective bits in either CCR, TBCTR or RBCTR.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>                 //Declarations from DAVE Code Generation (includes SFR declaration)
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t status;
 *
 *    status = DAVE_Init();
 *
 *    if(status == DAVE_STATUS_FAILURE)
 *    {
 *      XMC_DEBUG("DAVE APPs initialization failed\n");
 *
 *      while(1U)
 *      {
 *
 *      }
 *    }
 *    I2C_MASTER_DisableEvent(&I2C_MASTER_0, XMC_I2C_CH_EVENT_NACK);
 *    while(1U)
 *    {
 *    }
 *  }
 * @endcode
 *
 */
__STATIC_INLINE void I2C_MASTER_DisableEvent(I2C_MASTER_t * const handle, uint32_t event)
{
  XMC_ASSERT("I2C_MASTER_DisableEvent: invalid handle", (handle != NULL))
  XMC_I2C_CH_DisableEvent(handle->channel, event);
}

/**
 * @brief Receives the ACK from slave
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return None
 *
 * \par<b>Description:</b><br>
 * After transmitting a byte, master receives the ack from slave.<br>
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    uint8_t index = 0, loc_index = 0;
 *    uint8_t rec_data[64];
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      // write to address 0
 *      I2C_MASTER_TransmitByte(&I2C_MASTER_0, 0x00);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      I2C_MASTER_SendRepeatedStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_READ);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      while(index < 16)
 *      {
 *        I2C_MASTER_ReceiveACK(&I2C_MASTER_0);
 *        index++;
 *      }
 *      //Wait when Rx FIFO is empty
 *      while(!I2C_MASTER_IsRXFIFOEmpty(&I2C_MASTER_0))
 *      {
 *        rec_data[loc_index++] = I2C_MASTER_GetReceivedByte(&I2C_MASTER_0);
 *      }
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 * @endcode
*/
__STATIC_INLINE void I2C_MASTER_ReceiveACK(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_ReceiveACK: invalid handle", (handle != NULL))
  XMC_I2C_CH_MasterReceiveAck(handle->channel);
}
/**
 * @brief Receives the NACK from slave
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return None
 *
 * \par<b>Description:</b><br>
 * After transmitting a byte, master receives the nack from slave.<br>
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.
 *
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS (0xA0)
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    uint32_t index = 0, loc_index = 0;
 *    uint8_t rec_data[64];
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      // write to address 0
 *      I2C_MASTER_TransmitByte(&I2C_MASTER_0, 0x00);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      I2C_MASTER_SendRepeatedStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_READ);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      while(index < 16)
 *      {
 *        I2C_MASTER_ReceiveACK(&I2C_MASTER_0);
 *        index++;
 *      }
 *      // only for the last byte
 *      I2C_MASTER_ReceiveNACK(&I2C_MASTER_0);
 *      //Wait when Rx FIFO is empty
 *      while(!I2C_MASTER_IsRXFIFOEmpty(&I2C_MASTER_0))
 *      {
 *        rec_data[loc_index++] = I2C_MASTER_GetReceivedByte(&I2C_MASTER_0);
 *      }
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 * @endcode
*/
__STATIC_INLINE void I2C_MASTER_ReceiveNACK(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_ReceiveNACK: invalid handle", (handle != NULL))
  XMC_I2C_CH_MasterReceiveNack(handle->channel);
}
/**
 * @brief Sends stop command to slave
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return None
 *
 * \par<b>Description:</b><br>
 * At the end of transmission, sends a stop command to slave <br>
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet.<br>
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS (0xA0)
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while(I2C_MASTER_GetFlagStatus(&I2C_MASTER_0, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *       // wait for ACK
 *      }
 *      I2C_MASTER_ClearFlag(&I2C_MASTER_0,XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *      //send the address to which data to be transfered
 *      XMC_I2C_CH_MasterTransmit(I2C_MASTER_0.channel, 0x00);
 *      while((XMC_I2C_CH_GetStatusFlag(I2C_MASTER_0.channel) & XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *      }
 *      XMC_I2C_CH_ClearStatusFlag(I2C_MASTER_0.channel, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);

 *      I2C_MASTER_SendStop(&I2C_MASTER_0);
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *    return 1U;
 *  }
 * @endcode
*/
__STATIC_INLINE void I2C_MASTER_SendStop(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_SendStop: invalid handle", (handle != NULL))
  XMC_I2C_CH_ClearStatusFlag(handle->channel, XMC_I2C_CH_STATUS_FLAG_STOP_CONDITION_RECEIVED);
  XMC_I2C_CH_MasterStop(handle->channel);
}
/**
 * @brief Sends start command to slave
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param address slave address
 * @param cmd     command
 * @return None
 *
 * \par<b>Description:</b><br>
 * Before start of transmission, sends a start command to slave. \n
 * Address(address) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write).<br>
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet. <br>
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>
 *  #define SLAVE_ADDRESS 0xA0
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      I2C_MASTER_SendStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while((XMC_I2C_CH_GetStatusFlag(I2C_MASTER_0.channel) & XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *      }
 *      XMC_I2C_CH_ClearStatusFlag(I2C_MASTER_0.channel, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);

 *      //send the address to which data to be transfered
 *      XMC_I2C_CH_MasterTransmit(I2C_MASTER_0.channel, 0x00);
 *      while((XMC_I2C_CH_GetStatusFlag(I2C_MASTER_0.channel) & XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *      }
 *      XMC_I2C_CH_ClearStatusFlag(I2C_MASTER_0.channel, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 *    }
 *    else
 *    {
 *       XMC_DEBUG("main: Application initialization failed");
 *       while(1U)
 *       {
 *       }
 *    }
 *    return 1U;
 *   }
 * @endcode
*/
__STATIC_INLINE void I2C_MASTER_SendStart(I2C_MASTER_t * const handle, const uint32_t address,
		                                  const XMC_I2C_CH_CMD_t cmd)
{
  XMC_ASSERT("I2C_MASTER_SendStart: invalid handle", (handle != NULL))
  XMC_I2C_CH_ClearStatusFlag(handle->channel, XMC_I2C_CH_STATUS_FLAG_START_CONDITION_RECEIVED);
  XMC_I2C_CH_MasterStart(handle->channel, (uint16_t)address, cmd);
}
/**
 * @brief Sends repeated start command to slave
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @param address slave address
 * @param cmd     command
 * @return None
 *
 * \par<b>Description:</b><br>
 * Before start of transmission, sends a repeatedstart command to slave if bus acquired is true.\n
 * Address(address) should reserve an additional bit at the LSB for read/write indication. For example, address 0x05 should
 * be provided as 0x0a. If the address is 10-bit, only most significant bits with the 10-bit identifier should be sent using this function.
 * For example, if the 10-bit address is 0x305, the address should be provided as 0xf6(prepend with 0b11110, upper two bits of address 0b11,
 * followed by 1-bit field for read/write).<br>
 * Pre-requisite: Instantiate I2C_MASTER APP and generate code before using below code snippet. <br>
 * Example Usage:
 * @code
 *
 *  #include <DAVE.h>         //Declarations from DAVE Code Generation (includes SFR declaration)
 *  #define SLAVE_ADDRESS 0xA0
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    uint8_t rx_buf[256];
 *
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      XMC_I2C_CH_MasterStart(I2C_MASTER_0.channel, SLAVE_ADDRESS, XMC_I2C_CH_CMD_WRITE);
 *      while((XMC_I2C_CH_GetStatusFlag(I2C_MASTER_0.channel) & XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *      {
 *      }
 *      XMC_I2C_CH_ClearStatusFlag(I2C_MASTER_0.channel, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);

 *     //send the address to which data to be transfered
 *     XMC_I2C_CH_MasterTransmit(I2C_MASTER_0.channel, 0x00);
 *     while((XMC_I2C_CH_GetStatusFlag(I2C_MASTER_0.channel) & XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *     {
 *     }
 *     XMC_I2C_CH_ClearStatusFlag(I2C_MASTER_0.channel, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);

 *     I2C_MASTER_SendRepeatedStart(&I2C_MASTER_0, SLAVE_ADDRESS, XMC_I2C_CH_CMD_READ);
 *     while((XMC_I2C_CH_GetStatusFlag(I2C_MASTER_0.channel) & XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U)
 *     {
 *     }
 *
 *     XMC_I2C_CH_ClearStatusFlag(I2C_MASTER_0.channel, XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED);
 * 	   memset(rx_buf,0,16);
 *     I2C_MASTER_Receive(&I2C_MASTER_0, false, SLAVE_ADDRESS, rx_buf, 16, true, true);
 *    }
 *    else
 *    {
 *      XMC_DEBUG("main: Application initialization failed");
 *      while(1U)
 *      {
 *      }
 *    }
 *   return 1U;
 *  }
 * @endcode
*/
__STATIC_INLINE void I2C_MASTER_SendRepeatedStart(I2C_MASTER_t * const handle, const uint32_t address,
		                                          const XMC_I2C_CH_CMD_t cmd)
{
  XMC_ASSERT("I2C_MASTER_SendRepeatedStart: invalid handle", (handle != NULL))
  XMC_I2C_CH_ClearStatusFlag(handle->channel, XMC_I2C_CH_STATUS_FLAG_REPEATED_START_CONDITION_RECEIVED);
  XMC_I2C_CH_MasterRepeatedStart(handle->channel, (uint16_t)address, cmd);
}

/**
 * @brief Sends the txbusy flag
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return bool : status of txbusy flag
 
 * @code
 *
 *  #include <DAVE.h>
 *  #define SLAVE_ADDRESS (0xA0)
 *  typedef enum PCA9502_REGADDR {
 *    IO_DIR    = 0xA << 3,
 *    IO_STATE  = 0xB << 3,
 *    IO_INTE   = 0xC << 3,
 *    IO_CTRL   = 0xE << 3
 *  } PCA9502_REGADDR_t;
 *
 *  uint8_t tx_buffer[64] = {0x01,0x02,0x03,0x04,0x05};
 *  uint8_t mem_address[2];
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *     mem_address[0] = IO_STATE;//memory which need to be read from slave
 *     //Write data to IO EXPANDER
 *     I2C_MASTER_Transmit(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *     I2C_MASTER_Transmit(&I2C_MASTER_0,false,SLAVE_ADDRESS,tx_buffer,5,true);
 *     while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *    }
 *    while(1)
 *    { }

 *    return 0;
 *  }
 *
 * @endcode<BR> </p>
 *
 */
__STATIC_INLINE bool I2C_MASTER_IsTxBusy(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_IsTxBusy: invalid handle", (handle != NULL))	
  return handle->runtime->tx_busy;
}

/**
 * @brief Sends the rxbusy flag
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return bool : status of rxbusy flag
 * @code
 *
 *  #include <DAVE.h>
 *  #define SLAVE_ADDRESS (0xA0)
 *  #define BYTES_TO_READ 10
 *  #define BYTES_TO_TRANSMIT 10
 *
 *  typedef enum PCA9502_REGADDR {
 *    IO_DIR    = 0xA << 3,
 *    IO_STATE  = 0xB << 3,
 *    IO_INTE   = 0xC << 3,
 *    IO_CTRL   = 0xE << 3
 *  } PCA9502_REGADDR_t;

 *  uint8_t mem_address[2];
 *  uint8_t data = 0x55;
 *  uint8_t rx_data;
 *
 *  int main(void)
 *  {
 *    DAVE_STATUS_t init_status;
 *    init_status = DAVE_Init();
 *    if(init_status == DAVE_STATUS_SUCCESS)
 *    {
 *      mem_address[0] = IO_STATE;//memory which need to be read from slave
 *      //Write data to IO EXPANDER
 *      I2C_MASTER_Transmit(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *      I2C_MASTER_Transmit(&I2C_MASTER_0,false,SLAVE_ADDRESS,&data,1,true);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));

 *      //Read data from IO EXPANDER
 *      I2C_MASTER_Transmit(&I2C_MASTER_0,true,SLAVE_ADDRESS,mem_address,1,false);
 *      while(I2C_MASTER_IsTxBusy(&I2C_MASTER_0));
 *
 *      I2C_MASTER_Receive(&I2C_MASTER_0,true,SLAVE_ADDRESS,&rx_data,1,true,true);
 *      while(I2C_MASTER_IsRxBusy(&I2C_MASTER_0));
 *     }
 *     while(1)
 *     { }

 *    return 0;
 *  }
 *
 * @endcode<BR> </p>
 *
 */
__STATIC_INLINE bool I2C_MASTER_IsRxBusy(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_IsRxBusy: invalid handle", (handle != NULL))	
  return handle->runtime->rx_busy;
}

/**
 * @brief Flush TX FIFO
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return None
 *
 */
__STATIC_INLINE void I2C_MASTER_FlushTxFifo(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_FlushTxFifo: invalid handle", (handle != NULL))
  XMC_USIC_CH_TXFIFO_Flush(handle->channel);
}

/**
 * @brief Flush RX FIFO
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return None
 *
 */
__STATIC_INLINE void I2C_MASTER_FlushRxFifo(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_FlushRxFifo: invalid handle", (handle != NULL))
  XMC_USIC_CH_RXFIFO_Flush(handle->channel);
}

/**
 * @brief Disable output pins SDA/SCL
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return None
 *
 */
__STATIC_INLINE void I2C_MASTER_DisableIO(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_DisableOutputs: invalid handle", (handle != NULL))
  handle->config->fptr_i2c_disable_io();
}

/**
 * @brief Enable output pins SDA/SCL
 * @param handle  I2C_MASTER APP handle pointer of type @ref I2C_MASTER_t
 * @return None
 *
 */
__STATIC_INLINE void I2C_MASTER_EnableIO(I2C_MASTER_t * const handle)
{
  XMC_ASSERT("I2C_MASTER_EnableOutputs: invalid handle", (handle != NULL))
  handle->config->fptr_i2c_enable_io();
}

/**
 *@}
 */
 
#include "i2c_master_extern.h"

#ifdef __cplusplus
}
#endif  

#endif /* I2C_MASTER_H */

